<template>
    <div class="dataContainer">
        <span v-if="showErMsg" class="errMsg">未检索到指定内容</span>
        <el-scrollbar ref="scrollbar">
            <ul v-if="isHtml">
                <li v-for="item in dataArray" :key="item.Id" class="li">
                    <pre v-html="item.Content"></pre>
                </li>
            </ul>
            <ul v-else>
                <li v-for="item in dataArray" :key="item.Id" class="li">
                    {{ item.Content }}
                </li>
            </ul>
        </el-scrollbar>
    </div>
</template>

<script lang="ts">
import { defineComponent, ref, watch, onMounted, onBeforeUnmount, nextTick } from "vue";
import type { DataStruct, DataContainerInitProps, PaginagedData } from "@/components/public/DataContainer/DataContainer";
import { DataLoader } from "@/utils/dataLoader";

export default defineComponent({
    name: "DataContainer",
    props: {
        dataList: {
            type: String,
            default: "",
        },
        initProps: {
            type: String,
            default: "",
        },
        dataSingle: {
            type: String,
            default: "",
        },
    },
    setup(props, { emit }) {
        const dataArray = ref<DataStruct[]>([]);
        const isHtml = ref(false);
        const isStayTop = ref(true);
        const initPropsObj = ref<DataContainerInitProps | null>(null);
        const showErMsg = ref(false);
        const scrollbar = ref<HTMLElement | null>(null);
        let dataLoader: DataLoader | null = null;

        const dataSingleChange = (val: string) => {
            const dataSingle = JSON.parse(val) as DataStruct;
            dataArray.value.push(dataSingle);
            if (dataArray.value.length > 100) {
                dataArray.value = dataArray.value.slice(-100);
            }
            nextTick(() => {
                if (scrollbar.value) {
                    (scrollbar.value as any).wrapRef.scrollTop = (scrollbar.value as any).wrapRef.scrollHeight;
                }
            });
        };

        const initPropsChange = (val: string) => {

            initPropsObj.value = JSON.parse(val) as DataContainerInitProps;
            isStayTop.value = initPropsObj.value.isBottomScroll;
            isHtml.value = initPropsObj.value.isHtml;

            if (dataLoader === null) {
                dataLoader = new DataLoader(
                    initPropsObj.value.paginatedData.pageSize,
                    initPropsObj.value.paginatedData.totalDataCount,
                    (scrollbar.value as any).wrapRef,
                    initPropsObj.value.isBottomScroll,
                    onLoadCallback
                );
            } else {
                dataLoader.updatePaginInfo(initPropsObj.value.paginatedData.currentIndex, initPropsObj.value.paginatedData.totalDataCount);
            }
        };

        const dataListChange = (val: string) => {
            const dataList = JSON.parse(val) as DataStruct[];
            dataArray.value = [...dataList];
        };

        const onLoadCallback = async (data: any) => {
            const paginatedData = {
                currentIndex: data.currentIndex,
                pageSize: data.pageSize,
                totalDataCount: data.totalDataCount,
            } as PaginagedData;
            emit("callback", paginatedData);
        };

        const searchInfo = (inputTxt: string) => {
            showErMsg.value = false;
            if (!isHtml.value) return;

            // 清除之前的高亮显示
            dataArray.value.forEach((item) => {
                item.Content = item.Content.replace(/<span class="highlight">(.*?)<\/span>/g, (match, p1) => p1);
            });

            if (!inputTxt.trim()) return;

            // 高亮显示新的搜索内容
            const regex = new RegExp(`(${inputTxt.trim()})`, "gi");
            dataArray.value.forEach((item) => {
                item.Content = item.Content.replace(regex, '<span class="highlight">$1</span>');
            });

            nextTick(() => {
                const firstHighlight = document.querySelector(".highlight");
                if (firstHighlight) {
                    showErMsg.value = false;
                    if (scrollbar.value) {
                        (scrollbar.value as any).wrapRef.scrollTop = (firstHighlight as HTMLElement).offsetTop;
                    }
                } else {
                    showErMsg.value = true;
                }
            });
        };

        onMounted(() => {
            const initProps = JSON.parse(props.initProps) as DataContainerInitProps;
            if (initProps && initProps.isHtml) {
                isHtml.value = initProps.isHtml;
            }
        });

        onBeforeUnmount(() => {
            dataLoader?.destroy();
            dataLoader = null;
        });

        watch(() => props.dataSingle, dataSingleChange);
        watch(() => props.initProps, initPropsChange);
        watch(() => props.dataList, dataListChange);

        return {
            dataArray,
            isHtml,
            isStayTop,
            showErMsg,
            scrollbar,
            searchInfo,
        };
    },
});
</script>

<style lang="scss" scoped>
.dataContainer {
    height: 100%;
    width: 100%;
    overflow: hidden;

    .errMsg {
        color: red;
        text-align: right;
    }

    ul {
        height: 100%;

        li {
            font-size: 14px;
            margin-left: 15px;
            margin-top: 5px;
            color: black;
            list-style-type: none;
        }

        .li:nth-child(1) {
            margin-top: 0;
        }

        :deep(.highlight) {
            background-color: blue;
            color: white;
        }
    }
}
</style>